package com.catazy.mvvmlib.ext.download

import android.os.Looper
import com.catazy.mvvmlib.util.LogUtil
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.isActive
import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import java.io.File
import java.util.concurrent.TimeUnit

/**
 * 作者: Tao
 * 日期: 2024/1/31
 * 时间: 15:31
 * 描述: 下载管理类
 */
object DownLoadManager {

    private val retrofitBuilder by lazy {
        Retrofit.Builder()
            .baseUrl("https://www.baidu.com")
            .client(
                OkHttpClient.Builder()
                    .connectTimeout(10, TimeUnit.SECONDS)
                    .readTimeout(5, TimeUnit.SECONDS)
                    .writeTimeout(5, TimeUnit.SECONDS)
                    .build(
                    )
            ).build()
    }

    /**
     * 开始下载
     * @param tag String 标识
     * @param url String 下载的url
     * @param savePath String 保存的路径
     * @param saveName String 保存的名字
     * @param reDownload Boolean 如果文件已存在是否需要重新下载 默认不需要重新下载
     * @param loadListener OnDownloadListener
     */
    suspend fun downLoad(
        tag: String,
        url: String,
        savePath: String,
        saveName: String,
        reDownload: Boolean = false,
        loadListener: OnDownloadListener
    ) {
        withContext(Dispatchers.IO) {
            doDownLoad(tag, url, savePath, saveName, reDownload, loadListener, this)
        }
    }

    /**
     * 下载
     * @param tag String 标识
     * @param url String 下载的url
     * @param savePath String 保存的路径
     * @param saveName String 保存的名字
     * @param reDownload Boolean 如果文件已存在是否需要重新下载 默认不需要重新下载
     * @param loadListener OnDownloadListener
     * @param coroutineScope CoroutineScope 协程域
     */
    private suspend fun doDownLoad(
        tag: String,
        url: String,
        savePath: String,
        saveName: String,
        reDownload: Boolean = false,
        loadListener: OnDownloadListener,
        coroutineScope: CoroutineScope
    ) {
        //判断是否已经在下载池中
        val scope = DownLoadPool.getScopeFromKey(tag)
        if (scope != null && scope.isActive) {
//            loadListener.onDownloadError(tag, Throwable("The download task already exists"))
            return
        } else if (scope != null && !scope.isActive) {
            LogUtil.i("The download task already exists but is not active")
            DownLoadPool.removeScopeSp(tag)
        }
        //判断保存名称是否为空
        if (saveName.isEmpty()) {
            withContext(Dispatchers.Main) {
                loadListener.onDownloadError(tag, Throwable("The saveName is empty"))
            }
            return
        }
        //判断保存路径是否为空
        if (savePath.isEmpty()) {
            withContext(Dispatchers.Main) {
                loadListener.onDownloadError(tag, Throwable("The savePath is empty"))
            }
            return
        }
        //下载任务不能再主线程进行
        if (Looper.getMainLooper().thread == Thread.currentThread()) {
            withContext(Dispatchers.Main) {
                loadListener.onDownloadError(
                    tag,
                    Throwable("The download cannot be started on the main thread")
                )
            }
            return
        }
        val file = File("$savePath/$saveName")
        val currentLength = if (!file.exists()) {
            0L
        } else {
            file.length()
        }
        if (file.exists() && currentLength == 0L && !reDownload) {
            //文件已存在了
            withContext(Dispatchers.Main) {
                loadListener.onDownloadSuccess(tag, file.path, file.length())
            }
            return
        }

        //开始下载
        LogUtil.i("startDownLoad current $currentLength")

        try {
            //添加到下载池中
            DownLoadPool.add(tag, coroutineScope)
            DownLoadPool.add(tag, loadListener)
            DownLoadPool.add(tag, "$savePath/$saveName")
            //回调下载已经准备好了
            withContext(Dispatchers.Main) {
                loadListener.onDownloadPrepare(tag)
            }
            val response = retrofitBuilder.create(DownLoadService::class.java)
                .downloadFile("bytes=$currentLength-", url)
            val responseBody = response.body()
            if (responseBody == null) {
                LogUtil.i("responseBody is null please check download url")
                withContext(Dispatchers.Main) {
                    loadListener.onDownloadError(
                        tag,
                        Throwable("responseBody is null please check download url")
                    )
                }
                DownLoadPool.remove(tag)
                return
            }
            FileTool.downToFile(
                tag,
                savePath,
                saveName,
                currentLength,
                responseBody,
                loadListener
            )
        } catch (throwable: Throwable) {
            withContext(Dispatchers.Main) {
                loadListener.onDownloadError(tag, throwable)
            }
            DownLoadPool.remove(tag)
        }

    }
}